package com.zoro.barn.business.service.login.business.normalpassword.util.token;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.zoro.barn.commons.tools.encoding.Base64Util;
import com.zoro.barn.commons.tools.encryption.EncryptUtils;
import com.zoro.barn.commons.tools.json.JsonUtil;
import org.apache.commons.lang3.StringUtils;

/**
 * @author zhaoxingwu
 */
public class TokenUtil {

    private static final String HEADER_TYP = "typ";
    private static final String HEADER_TYP_VALUE = "JWT";
    private static final String HEADER_ALG = "alg";
    private static final String HEADER_ALG_VALUE = "HS256";

    private static final String HEADER_BASE64;

    private static final String SEPARATOR = ".";
    private static final String SEPARATOR_PATTERN = "\\" + SEPARATOR;

    static {
        ObjectNode objectNode = JsonUtil.makeJsonObject()
                .put(HEADER_TYP, HEADER_TYP_VALUE)
                .put(HEADER_ALG, HEADER_ALG_VALUE);
        HEADER_BASE64 = Base64Util.urlEncoding(objectNode.toString());

    }

    private static String headerBase64() {
        return HEADER_BASE64;
    }

    private static String token(String headerBase64, String payloadBase64, String secret) {

        String sign = makeSign(headerBase64, payloadBase64, secret);
        return headerBase64 + SEPARATOR + payloadBase64 + SEPARATOR + sign;
    }

    public static String token(String payload, String secret) {
        return token(headerBase64(), Base64Util.urlEncoding(payload), secret);
    }

    public static boolean isLegal(String token, String secret) {
        if (StringUtils.isBlank(token)) {
            return false;
        }
        String[] claims = token.split(SEPARATOR_PATTERN);
        if (claims.length != 3) {
            return false;
        }
        String newSign = makeSign(claims[0], claims[1], secret);
        String checkSign = claims[2];
        return StringUtils.equals(newSign, checkSign);

    }

    /**
     * 生成 签名部分
     *
     * @param headerBase64  base64以后的头部分
     * @param payloadBase64 base64以后的payload部分
     * @param secret        密钥
     * @return sign
     */
    private static String makeSign(String headerBase64, String payloadBase64, String secret) {
        return EncryptUtils.sha256(headerBase64 + SEPARATOR + payloadBase64 + SEPARATOR + secret);
    }

    /**
     * 获取 payload部分的字符串
     *
     * @param token token
     * @return payload , not decoding
     */
    public static String getPayload(String token) {
        if (StringUtils.isBlank(token)) {
            return null;
        }

        String[] claims = token.split(SEPARATOR_PATTERN);
        if (claims.length != 3) {
            return null;
        }
        return claims[1];
    }

    /**
     * 获取token 的 payload 对象
     *
     * @param token token
     * @return payload
     */
    public static TokenPayload getPayloadObject(String token) {

        String payload = getPayload(token);
        if (StringUtils.isBlank(payload)) {
            return null;
        }
        try {
            String payloadJson = Base64Util.urlDecoding(payload);
            return TokenPayload.builder().from(JsonUtil.readJsonObject(payloadJson)).buildObject();
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }
}
